package com.easylinkin.linkappapi.lobar.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.easylinkin.linkappapi.common.model.RequestModel;
import com.easylinkin.linkappapi.common.utils.excel.ExcelConstant;
import com.easylinkin.linkappapi.common.utils.excel.ExcelTools;
import com.easylinkin.linkappapi.common.utils.io.OutputStreamUtil;
import com.easylinkin.linkappapi.lobar.dto.UserClockDTO;
import com.easylinkin.linkappapi.lobar.dto.UserProjectDTO;
import com.easylinkin.linkappapi.lobar.dto.UserRecordDTO;
import com.easylinkin.linkappapi.lobar.entity.UserClock;
import com.easylinkin.linkappapi.lobar.entity.UserRecord;
import com.easylinkin.linkappapi.lobar.entity.UserStatistics;
import com.easylinkin.linkappapi.lobar.mapper.UserProjectMapper;
import com.easylinkin.linkappapi.lobar.service.UserClockService;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import java.io.IOException;
import java.io.OutputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import site.morn.rest.RestBuilders;
import site.morn.rest.RestMessage;

/**
 * @author: kan yuanfeng
 * @Date: 2020/11/04 11:42
 * @Description: 考勤管理
 */
@RestController
@RequestMapping("userClock")
@Api(tags = "考勤管理")
public class UserClockController {
  
  @Autowired
  private UserClockService userClockService;
  @Autowired
  private UserProjectMapper userProjectMapper;
  @Autowired
  private LinkappUserContextProducer linkappUserContextProducer;

  /**
   * @Description: 增加考勤
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @PostMapping
  @ApiOperation("增加考勤")
  public RestMessage insert(@RequestBody UserClock userClock){
    //todo 参数验证
    //查询用户的班组和参建单位id
    UserProjectDTO userProjectDTO = userProjectMapper.findByUserId(userClock.getUserId(),
        linkappUserContextProducer.getNotNullCurrent().getTenantId());
    userClock.setCompanyProjectId(userProjectDTO.getCompanyProjectId());
    userClock.setGroupId(userProjectDTO.getGroupId());
    userClock.setTenantId(userProjectDTO.getTenantId());
    userClockService.insert(userClock);
    return RestBuilders.successBuilder().build();
  }

  /**
   * @Description: 删除考勤（包含批量删除）
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @DeleteMapping
  @ApiOperation("删除考勤（包含批量删除）")
  public RestMessage delBatch(@RequestBody UserClock userClock){
    Assert.notEmpty(userClock.getIds(),"id不能为空");
    userClockService.delBatch(userClock.getIds());
    return RestBuilders.successBuilder().build();
  }

  /**
   * @Description: 编辑考勤
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @PutMapping
  @ApiOperation("编辑考勤")
  public RestMessage updateById(@RequestBody UserClock userClock){
    Assert.notNull(userClock.getId(),"id不能为空");
    userClockService.updateOne(userClock);
    return RestBuilders.successBuilder().build();
  }

  /**
   * @Description: 根据id查询考勤详情
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @GetMapping("{id}")
  @ApiOperation("根据id查询考勤详情")
  public RestMessage findById(@PathVariable("id")String id) {
    Assert.notNull(id,"id不能为空");
    UserClock userClock = userClockService.getById(id);
    return RestBuilders.successBuilder().data(userClock).build();
  }

  /**
   * @Description: 根据条件，分页(不分页)查询
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @PostMapping("list")
  @ApiOperation("根据条件，分页(不分页)查询")
  public RestMessage queryListByPage(@RequestBody RequestModel<UserClockDTO> requestModel){
    Assert.notNull(requestModel.getCustomQueryParams(), "customQueryParams 不能为空");
    Assert.notNull(requestModel.getPage(), "page 不能为空");
    IPage<UserClockDTO> record =  userClockService.queryListByPage(requestModel);
    return RestBuilders.successBuilder().data(record).build();
  }

  /**
   * @Description: 根据条件，分页(不分页)查询月视图
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @PostMapping("month/list")
  @ApiOperation("根据条件，分页(不分页)查询月视图")
  public RestMessage queryMonthByPage(@RequestBody RequestModel<UserClockDTO> requestModel)
      throws ExecutionException, InterruptedException {
    Assert.notNull(requestModel.getCustomQueryParams(), "customQueryParams 不能为空");
    Assert.notNull(requestModel.getPage(), "page 不能为空");
    IPage<UserClockDTO> record =  userClockService.queryMonthByPage(requestModel);
    return RestBuilders.successBuilder().data(record).build();
  }

  /**
   * @Description: 根据条件，分页(不分页)查询考勤报表
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @PostMapping("record")
  @ApiOperation("根据条件，分页(不分页)查询")
  public RestMessage queryRecordByPage(@RequestBody RequestModel<UserClockDTO> requestModel){
    Assert.notNull(requestModel.getCustomQueryParams(), "customQueryParams 不能为空");
    Assert.notNull(requestModel.getPage(), "page 不能为空");
    IPage<UserClockDTO> record =  userClockService.queryRecordByPage(requestModel);
    return RestBuilders.successBuilder().data(record).build();
  }

  /**
   * @Description: 根据条件，分页(不分页)查询考勤统计
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @PostMapping("statistics")
  @ApiOperation("根据条件，分页(不分页)查询考勤统计")
  public RestMessage queryStatistics(@RequestBody RequestModel<UserClockDTO> requestModel){
    Assert.notNull(requestModel.getCustomQueryParams(), "customQueryParams 不能为空");
    Assert.notNull(requestModel.getPage(), "page 不能为空");
    IPage<UserStatistics> record =  userClockService.queryStatistics(requestModel);
    return RestBuilders.successBuilder().data(record).build();
  }

  /**
   * @Description: 获取当前月的开始时间，结束时间
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @GetMapping("month")
  @ApiOperation("获取当前月的开始时间，结束时间")
  public RestMessage getMonth(){
    Date begin = DateUtil.beginOfMonth(new Date());
    Date end = DateUtil.endOfMonth(new Date());
    UserClockDTO userClockDTO = new UserClockDTO();
    userClockDTO.setStartTime(begin);
    userClockDTO.setEndTime(end);
    return RestBuilders.successBuilder().data(userClockDTO).build();
  }

  /**
   * @Description: 根据条件，导出
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @PostMapping("month/export")
  @ApiOperation("根据条件，导出")
  public void monthExport(@RequestBody RequestModel<UserClockDTO> requestModel, HttpServletRequest request, HttpServletResponse response)
      throws InterruptedException, ExecutionException {
    requestModel.getPage().setSize(-1);
    IPage<UserClockDTO> iPage = userClockService.monthExport(requestModel);
    List<Map<String, Object>> maps = new ArrayList<>();
    if (null != iPage.getRecords() && iPage.getRecords().size()>0){
      for (int i = 0; i < iPage.getRecords().size(); i++) {
        UserClockDTO clockDTO = iPage.getRecords().get(i);
        Map<String, Object> map = new HashMap<>();
        map.put("id",i+1);
        map.put("userName",clockDTO.getUserName());
        clockDTO.getMouthList().forEach(m ->{
          map.put(m.getId(),m.getOnFlagStr());
        });
        map.put("count",clockDTO.getOnNum());
        maps.add(map);
      }
    }
    //计算总天数
    String[] split = requestModel.getCustomQueryParams().getMouthStr().split("-");
    int lengthOfMonth = DateUtil
        .lengthOfMonth(Integer.valueOf(split[1]), DateUtil.isLeapYear(Integer.valueOf(split[0])));
    String keyValue = "序号:id,姓名:userName";
    for (int i = 1; i <= lengthOfMonth; i++) {
      keyValue += ","+i+":"+i;
    }
    keyValue += ",合计:count";
    String title = requestModel.getCustomQueryParams().getMouthStr()+"考勤工日管理";
    String fileName = title + ".xls";
    try {
      OutputStream outputStream = OutputStreamUtil
          .getOutputStream(request, response, fileName);
      ExcelTools.exportExcel(outputStream, keyValue, maps, ExcelConstant.XLS, title);
      response.flushBuffer();
      outputStream.close();
    } catch (IOException e) {
      throw new RuntimeException("excel导出失败！IOException异常" + e.getMessage());
    } catch (Exception e) {
      throw new RuntimeException("excel导出失败！" + e.getMessage());
    }
  }

  /**
   * @Description: 根据条件，导出考勤
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @PostMapping("export")
  @ApiOperation("根据条件，导出考勤")
  public void export(@RequestBody RequestModel<UserClockDTO> requestModel, HttpServletRequest request, HttpServletResponse response) {
    requestModel.getPage().setSize(-1);
    IPage<UserClockDTO> iPage = userClockService.queryListByPage(requestModel);
    iPage.getRecords().forEach(r ->{
      //数据转换
      if (null != r.getClockTime()){
        r.setClockTimeStr(new SimpleDateFormat("yyyy-MM-dd").format(r.getClockTime()));
      }
    });
    String keyValue = "月份:mouthStr,姓名:userName,班组:groupName," +
        "参建单位:companyName,工种:workType,出勤天数:onNum,缺勤天数:offNum,最近考勤:clockTimeStr";
    String title = "人员考勤";
    String fileName = title + ".xls";
    try {
      OutputStream outputStream = OutputStreamUtil
          .getOutputStream(request, response, fileName);
      ExcelTools.exportExcel(outputStream, keyValue, iPage.getRecords(), ExcelConstant.XLS, title);
      response.flushBuffer();
      outputStream.close();
    } catch (IOException e) {
      throw new RuntimeException("excel导出失败！IOException异常" + e.getMessage());
    } catch (Exception e) {
      throw new RuntimeException("excel导出失败！" + e.getMessage());
    }
  }

  /**
   * 手动触发定时任务
   * type = 1 表示触发所有项目
   * time 为需要统计的时间 当天就是传前一天的时间
   * 为空  本项目
   */
  @GetMapping("compute")
  @ApiOperation("手动触发定时任务")
  public RestMessage compute(Integer type,String time) throws ParseException {
    Date date = null;
    if (StringUtils.isNotBlank(time)){
      SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss");
      date = sdf.parse(time);
    }
    userClockService.compute(type,date);
    return RestBuilders.successBuilder().build();
  }

  /**
   * @Description: 根据条件，分页(不分页)查询月视图（工时统计）
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @PostMapping("month/list/hour")
  @ApiOperation("根据条件，分页(不分页)查询月视图（工时统计）")
  public RestMessage queryMonthHourByPage(@RequestBody RequestModel<UserClockDTO> requestModel)
          throws Exception{
    Assert.notNull(requestModel.getCustomQueryParams(), "customQueryParams 不能为空");
    Assert.notNull(requestModel.getPage(), "page 不能为空");
    IPage<UserClockDTO> record =  userClockService.queryMonthHourByPage(requestModel);
    return RestBuilders.successBuilder().data(record).build();
  }

  /**
   * @Description: 根据条件，导出工时
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @PostMapping("month/exportHour")
  @ApiOperation("根据条件，导出工时")
  public void monthExportHour(@RequestBody RequestModel<UserClockDTO> requestModel, HttpServletRequest request, HttpServletResponse response)
          throws Exception {
    requestModel.getPage().setSize(-1);
    IPage<UserClockDTO> iPage = userClockService.queryMonthHourByPage(requestModel);
    List<Map<String, Object>> maps = new ArrayList<>();
    if (CollectionUtil.isNotEmpty(iPage.getRecords())){
      for (int i = 0; i < iPage.getRecords().size(); i++) {
        UserClockDTO clockDTO = iPage.getRecords().get(i);
        Map<String, Object> map = new HashMap<>();
        map.put("id",i+1);
        map.put("userName",clockDTO.getUserName());
        map.put("companyName",clockDTO.getCompanyName());
        map.put("groupName",clockDTO.getGroupName());
        clockDTO.getMouthList().forEach(m ->{
          map.put(m.getId(),null!=m.getHours()?String.format("%.1f", m.getHours()):"");
        });
        map.put("avHours",null!=clockDTO.getAvHours()?String.format("%.1f", clockDTO.getAvHours()):"");
        map.put("sumHours",null!=clockDTO.getSumHours()?String.format("%.1f", clockDTO.getSumHours()):"");
        maps.add(map);
      }
    }
    //计算总天数
    String[] split = requestModel.getCustomQueryParams().getMouthStr().split("-");
    int lengthOfMonth = DateUtil
            .lengthOfMonth(Integer.valueOf(split[1]), DateUtil.isLeapYear(Integer.valueOf(split[0])));
    String keyValue = "序号:id,姓名:userName,单位:companyName,班组:groupName";
    for (int i = 1; i <= lengthOfMonth; i++) {
      keyValue += ","+i+":"+i;
    }
    keyValue += ",日均:avHours,总计:sumHours";
    String title = requestModel.getCustomQueryParams().getMouthStr()+"考勤工时管理";
    String fileName = title + ".xls";
    try {
      OutputStream outputStream = OutputStreamUtil
              .getOutputStream(request, response, fileName);
      ExcelTools.exportExcel(outputStream, keyValue, maps, ExcelConstant.XLS, title);
      response.flushBuffer();
      outputStream.close();
    } catch (IOException e) {
      throw new RuntimeException("excel导出失败！IOException异常" + e.getMessage());
    } catch (Exception e) {
      throw new RuntimeException("excel导出失败！" + e.getMessage());
    }
  }

  /**
   * @Description: 根据条件，分页(不分页)查询人员考勤信息
   * @author kan yuanfeng
   * @date 2020/11/04 11:42
   */
  @PostMapping("findRecordByPage")
  @ApiOperation("根据条件，分页(不分页)查询")
  public RestMessage findRecordByPage(@RequestBody RequestModel<UserClockDTO> requestModel){
    Assert.notNull(requestModel.getCustomQueryParams(), "customQueryParams 不能为空");
    Assert.notNull(requestModel.getPage(), "page 不能为空");
    IPage<UserRecordDTO> record =  userClockService.findRecordByPage(requestModel);
    return RestBuilders.successBuilder().data(record).build();
  }
}

